package com.usian.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.type.TypeReference;
import com.usian.common.aliyun.OSSService;
import com.usian.common.constants.message.NewsAutoScanConstants;
import com.usian.common.dtos.PageResult;
import com.usian.common.enums.AppHttpCodeEnum;
import com.usian.common.exception.LeadException;
import com.usian.common.threadlocal.UserThreadLocalUtils;
import com.usian.common.util.BeanHelper;
import com.usian.common.util.JsonUtils;
import com.usian.model.admin.dtos.NewsAuthDto;
import com.usian.model.media.dtos.WmNewsDto;
import com.usian.model.media.dtos.WmNewsPageReqDto;
import com.usian.model.media.dtos.WmNewsResultDTO;
import com.usian.wemedia.entity.WmMaterial;
import com.usian.wemedia.entity.WmNews;
import com.usian.wemedia.entity.WmNewsMaterial;
import com.usian.wemedia.mapper.WmNewsMapper;
import com.usian.wemedia.service.IWmMaterialService;
import com.usian.wemedia.service.IWmNewsMaterialService;
import com.usian.wemedia.service.IWmNewsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.swagger.models.auth.In;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import static com.usian.common.constants.message.WmNewsUpDownConstants.WM_NEWS_UP_OR_DOWN_TOPIC;

/**
 * <p>
 * 自媒体图文内容信息表 服务实现类
 * </p>
 *
 * @author usian
 * @since 2022-07-08
 */
@Service
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements IWmNewsService {

    @Override
    public PageResult<WmNewsDto> findByPage(WmNewsPageReqDto dto) {
        //参数校验
        if (dto==null){
            throw new LeadException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //获取用户信息
        Integer userId = UserThreadLocalUtils.getUserId();
        if (userId==null){
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        //分页条件
        Page<WmNews> page=new Page<>(dto.getPage(),dto.getSize());
        //查询条件
        QueryWrapper<WmNews> queryWrapper=new QueryWrapper();
        //查询当前用户得文章
        queryWrapper.lambda().eq(WmNews::getWmUserId,userId);
        //根据关键字条件查询
        if (StringUtils.isNotBlank(dto.getKeyword()))
        queryWrapper.lambda().like(WmNews::getTitle,dto.getKeyword());
        //频道条件查询
        if (dto.getChannelId()!=null){
            queryWrapper.lambda().eq(WmNews::getChannelId,dto.getChannelId());
        }
        //设置发布日期条件
        if (dto.getBeginPubDate()!=null){
            //发布日期大于开始日期
            queryWrapper.lambda().ge(WmNews::getCreatedTime,dto.getBeginPubDate());
        }
        if (dto.getEndPubDate()!=null){
            //发布日期小于开始日期
            queryWrapper.lambda().le(WmNews::getCreatedTime,dto.getEndPubDate());
        }
        //设置状态查询条件
        Integer status = dto.getStatus();
        if (status!=null && status!=-1 ){
            //判断待审判状态， where status in（1，3）
            if (status == 1) {
                queryWrapper.lambda().in(WmNews::getStatus,new Integer[]{1,3});
            }else if (status==4){
                queryWrapper.lambda().in(WmNews::getStatus,new Integer[]{4,8,9});
            }else {
                queryWrapper.lambda().eq(WmNews::getStatus,status);
            }
        }
        //执行查询
        IPage<WmNews> iPage = this.page(page, queryWrapper);
        //封装分页查询结果
        if (CollectionUtils.isEmpty(iPage.getRecords())){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //数据转换
        List<WmNewsDto> newsDtoList = BeanHelper.copyWithCollection(iPage.getRecords(), WmNewsDto.class);

        return new PageResult<>(dto.getPage(),dto.getSize(),iPage.getTotal(),newsDtoList);
    }


    @Autowired
    private IWmNewsMaterialService wmNewsMaterialService;

    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;

    @Autowired
    private IWmMaterialService wmMaterialService;

    @Override
    public void saveNews(WmNewsDto wmNewsDto) {
        //参数校验
        if (wmNewsDto==null || wmNewsDto.getTitle()==null || wmNewsDto.getContent()==null){
            throw new LeadException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //获取当前用户
        Integer userId = UserThreadLocalUtils.getUserId();
        if (userId == null) {
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        //数据转换   wmNewsDto转成WmNews
        WmNews wmNews = BeanHelper.copyProperties(wmNewsDto, WmNews.class);
        //判断是保存文章还是修改文章
        if (wmNewsDto.getId() == null) {
            //id等于空说明是新增操作
            wmNews.setWmUserId(userId);
            wmNews.setCreatedTime(new Date());
            //新录入得文章都是下架状态
            wmNews.setEnable(false);
        }
        //判断是否存入草稿
        if (!wmNewsDto.getDraft()) {
            wmNews.setSubmitedTime(new Date());
        }
        //将前端提交得封面图片地址，以逗号分割，存到数据库中
        List<String> imagesList = wmNewsDto.getImages();
        if (!CollectionUtils.isEmpty(imagesList)){
            String images = imagesList.stream().collect(Collectors.joining(","));
            wmNews.setImages(images);
        }
        //执行新增或修改数据
        boolean b = this.saveOrUpdate(wmNews);
        if (!b) {
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
        }
        //维护自媒体文章与素材得关联关系

        //文章表和素材表是多对多关系，如果是修改文章表，需要先把中间表信息删除
        if (wmNewsDto.getId()!=null){
            wmNewsMaterialService.deleteByNewsId(wmNewsDto.getId());
        }
        //提交文章正文素材关联
        String content = wmNewsDto.getContent();
        List<Map<String, String>> contentList = JsonUtils.nativeRead(content, new TypeReference<List<Map<String, String>>>() {
        });
        //获取正文中得图片
        List<String> imageUrlList = parseImageUrl(contentList);

        //关联正文中素材（图片）与文章
        List<Integer> materialIds = null;
        if (!CollectionUtils.isEmpty(imageUrlList)) {
            //获取素材得id集合
            materialIds = getMaterialIds(userId,imageUrlList);
            //关联素材和文章
            wmNewsMaterialService.saveInfoBatch(wmNews.getId(),materialIds,0);
        }

        //获取封面中图片地址，进行文章与素材得关联
        if (!CollectionUtils.isEmpty(imagesList)) {
            //获取素材得id集合
            materialIds = getMaterialIds(userId,imagesList);
            //关联素材和文章
            wmNewsMaterialService.saveInfoBatch(wmNews.getId(),materialIds,1);
        }

        //生产自媒体文章审核消息（需要先判断是否是存入草稿，当不是存入草稿时，在生产消息）
        if (!wmNewsDto.getDraft()){
            kafkaTemplate.send(NewsAutoScanConstants.WM_NEWS_AUTO_SCAN_TOPIC,String.valueOf(wmNews.getId()));
        }




    }

    @Autowired
    private OSSService ossService;

    @Override
    public void deleteNews(Integer id) {
        // 参数校验
        if (id==null){
            throw new LeadException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //获取用户id
        Integer userId = UserThreadLocalUtils.getUserId();
        if (userId == null) {
        throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        //根据id和用户id查询文章
        QueryWrapper<WmNews> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WmNews::getId,id).eq(WmNews::getWmUserId,userId);
        WmNews wmNews = getOne(queryWrapper);
        if (wmNews == null) {
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"文章不存在");
        }
        //判断文章得状态是否是已发布且上架
        if (wmNews.getStatus().equals(WmNewsDto.Status.PUBLISHED) &&  wmNews.getEnable()){
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"当前文章已发布且已上架不可删除");
        }

        //获取图片名称，供阿里云删除
        String images = wmNews.getImages();
        String content = wmNews.getContent();

        //根据id删除文章
        removeById(id);

        //删除自媒体文章和素材关联关系
        wmNewsMaterialService.deleteByNewsId(id);
        //根据文章得名称删除阿里云上得图片资源
        if (StringUtils.isNotBlank(images)){
            String[] imagesList = images.split(",");
        //删除封面图片阿里云资源
        for (String image : imagesList) {
            int index = image.lastIndexOf("/") + 1;
            String imageName = image.substring(index);
            ossService.deleteFile(imageName);
        }
    }

        List<Map<String, String>> contentList = JsonUtils.nativeRead(content, new TypeReference<List<Map<String, String>>>() {
        });
        //获取正文中得图片
        List<String> imageUrlList = parseImageUrl(contentList);
        //删除正文图片阿里云资源
        for (String image : imageUrlList) {
            int index = image.lastIndexOf("/") + 1;
            String imageName = image.substring(index);
            ossService.deleteFile(imageName);
        }
    }

    @Override
    public void downOrUp(WmNewsDto wmNewsDto) {
        // 参数校验
        if (wmNewsDto==null  || wmNewsDto.getId()==null ||  wmNewsDto.getEnable()==null){
            throw new LeadException(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //获取用户id
        Integer userId = UserThreadLocalUtils.getUserId();
        if (userId == null) {
            throw new LeadException(AppHttpCodeEnum.NEED_LOGIN);
        }
        //根据id和用户id查询文章
        QueryWrapper<WmNews> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WmNews::getId,wmNewsDto.getId()).eq(WmNews::getWmUserId,userId);
        WmNews wmNews = getOne(queryWrapper);
        if (wmNews == null) {
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"文章不存在");
        }
        if (wmNews.getStatus() != WmNewsDto.Status.PUBLISHED.getCode()) {
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"文章未发布，不能上下架");
        }
        //实现文章上下架的功能
        WmNews wmNews1 = new WmNews();
        wmNews1.setId(wmNewsDto.getId());
        wmNews1.setEnable(wmNewsDto.getEnable());
        boolean b = updateById(wmNews1);
        if (!b) {
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR,"上下架失败");
        }

        //生成自媒体文章上下架得消息
        Map<String, Object> map = new HashMap<>();
        map.put("wmNewsId",wmNewsDto.getId());
        map.put("enable",wmNewsDto.getEnable()?1:0);
        kafkaTemplate.send(WM_NEWS_UP_OR_DOWN_TOPIC, JSON.toJSONString(map));

    }

    @Override
    public List<Integer> findWmNewsIds() {
        //设置查询条件，状态为8，并且发布时间小于当前时间
        QueryWrapper<WmNews> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WmNews::getStatus, WmNewsResultDTO.Status.SUCCESS.getCode()).lt(WmNews::getPublishTime,new Date());

        List<WmNews> wmNewsList= list(queryWrapper);
        if (CollectionUtils.isEmpty(wmNewsList)) {
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"审核通过待发布得文章不存在");
        }
        List<Integer> idList = wmNewsList.stream().map(WmNews::getId).collect(Collectors.toList());
        return idList;
    }
    @Override
    public PageResult<WmNewsResultDTO> findWmNewsPage(NewsAuthDto dto) {
        //封装分页查询条件
        Page page = new Page(dto.getPage(),dto.getSize());
        //封装文章标题模糊查询
        IPage<WmNewsResultDTO> iPage = this.getBaseMapper().selectWmNewsByPage(page,dto);
        if (iPage==null || CollectionUtils.isEmpty(iPage.getRecords())){
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        return new PageResult<>(dto.getPage(),dto.getSize(),iPage.getTotal(),iPage.getRecords());
    }

    //查询素材id集合
    private List<Integer> getMaterialIds(Integer userId, List<String> imageUrlList) {
        QueryWrapper<WmMaterial> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(WmMaterial::getUserId,userId).in(WmMaterial::getUrl,imageUrlList);
        List<WmMaterial> materialList = wmMaterialService.list(queryWrapper);

        if (CollectionUtils.isEmpty(materialList) ||  materialList.size() != imageUrlList.size()){
           throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST,"引用图片素材异常");
        }

        List<Integer> ids = materialList.stream().map(WmMaterial::getId).collect(Collectors.toList());
        return ids;
    }

    //解析正文图片集合
    private List<String> parseImageUrl(List<Map<String, String>> contentList) {
        //使用set集合去除重复得图片地址
        Set<String> set = new HashSet<>();
        //遍历集合，获取 集合中得图片地址
        for (Map<String, String> map : contentList) {
            if (map.get("type").equals("image")){
                String image = map.get("value");
                set.add(image);
            }
        }
        ArrayList<String> imageList = new ArrayList<>();
        imageList.addAll(set);
        return imageList;
    }
}
